import { HubConnectionBuilder, LogLevel } from '@microsoft/signalr'
import { useAuthStore } from '@/stores/auth'

class SignalRService {
  constructor() {
    this.connection = null
    this.privateMessageCallbacks = []
    this.groupMessageCallbacks = []
    this.userTypingCallbacks = []
    this.friendStatusCallbacks = []
    this.messageReadCallbacks = []
  }

  async startConnection() {
    const authStore = useAuthStore()
    
    if (!authStore.token) {
      console.error('No auth token available')
      return
    }
    
    this.connection = new HubConnectionBuilder()
      .withUrl('https://localhost:7220/chathub', {
        accessTokenFactory: () => authStore.token
      })
      .configureLogging(LogLevel.Information)
      .withAutomaticReconnect()
      .build()
    
    try {
      await this.connection.start()
      console.log('SignalR Connected successfully.')
    
      // Register server-side methods
      this.connection.on('ReceivePrivateMessage', (message) => {
        this.privateMessageCallbacks.forEach(callback => callback(message))
      })
      
      this.connection.on('ReceiveGroupMessage', (message) => {
        this.groupMessageCallbacks.forEach(callback => callback(message))
      })
      
      this.connection.on('UserTyping', (userId, isTyping) => {
        this.userTypingCallbacks.forEach(callback => callback(userId, isTyping))
      })
      
      this.connection.on('FriendStatusChanged', (userId, status) => {
        this.friendStatusCallbacks.forEach(callback => callback(userId, status))
      })
      
      this.connection.on('MessageRead', (messageId) => {
        this.messageReadCallbacks.forEach(callback => callback(messageId))
      })
    } catch (err) {
      console.error('Error while establishing SignalR connection: ', err)
      setTimeout(() => this.startConnection(), 5000)
    }
    
    this.connection.onclose(async () => {
      console.log('SignalR connection closed. Attempting to reconnect...')
    })
    
    this.connection.onreconnecting((error) => {
      console.log('SignalR reconnecting due to error: ', error)
    })
    
    this.connection.onreconnected((connectionId) => {
      console.log('SignalR reconnected with connectionId: ', connectionId)
    })
  }

  async stopConnection() {
    if (this.connection) {
      await this.connection.stop()
      this.connection = null
    }
  }

  async sendPrivateMessage(receiverId, content, messageType = 'text') {
    if (this.connection.state === 'Connected') {
      try {
        await this.connection.invoke('SendPrivateMessage', receiverId, content, messageType)
      } catch (err) {
        console.error('Error sending private message: ', err)
      }
    }
  }

  async sendGroupMessage(groupId, content, messageType = 'text') {
    if (this.connection.state === 'Connected') {
      try {
        await this.connection.invoke('SendGroupMessage', groupId, content, messageType)
      } catch (err) {
        console.error('Error sending group message: ', err)
      }
    }
  }

  async joinGroup(groupId) {
    if (this.connection.state === 'Connected') {
      try {
        await this.connection.invoke('JoinGroup', groupId)
      } catch (err) {
        console.error('Error joining group: ', err)
      }
    }
  }

  async leaveGroup(groupId) {
    if (this.connection.state === 'Connected') {
      try {
        await this.connection.invoke('LeaveGroup', groupId)
      } catch (err) {
        console.error('Error leaving group: ', err)
      }
    }
  }

  async typing(receiverId, isTyping) {
    if (this.connection.state === 'Connected') {
      try {
        await this.connection.invoke('Typing', receiverId, isTyping)
      } catch (err) {
        console.error('Error sending typing indicator: ', err)
      }
    }
  }

  async markMessageAsRead(messageId) {
    if (this.connection.state === 'Connected') {
      try {
        await this.connection.invoke('MarkMessageAsRead', messageId)
      } catch (err) {
        console.error('Error marking message as read: ', err)
      }
    }
  }

  onReceivePrivateMessage(callback) {
    this.privateMessageCallbacks.push(callback)
  }

  onReceiveGroupMessage(callback) {
    this.groupMessageCallbacks.push(callback)
  }

  onUserTyping(callback) {
    this.userTypingCallbacks.push(callback)
  }

  onFriendStatusChanged(callback) {
    this.friendStatusCallbacks.push(callback)
  }

  onMessageRead(callback) {
    this.messageReadCallbacks.push(callback)
  }
}

export const signalRService = new SignalRService()